package timing.ukulele.storage.service;

import io.minio.Result;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import timing.ukulele.common.data.ResponseCode;
import timing.ukulele.common.data.ResponseData;
import timing.ukulele.storage.repository.GroupRepository;
import timing.ukulele.storage.entity.GroupEntity;
import timing.ukulele.storage.service.minio.BucketService;
import timing.ukulele.storage.util.UpdateUtil;

import java.security.acl.Group;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class GroupService {
    private final GroupRepository repository;
    private final MongoOperations mongoOperations;
    private final BucketService bucketService;

    public GroupService(GroupRepository groupRepository, MongoOperations mongoOperations, BucketService bucketService) {
        this.repository = groupRepository;
        this.mongoOperations = mongoOperations;
        this.bucketService = bucketService;
    }

    public boolean existed(GroupEntity filter) {
        Optional<GroupEntity> one = repository.findOne(Example.of(filter));
        return one.isPresent();
    }

    public GroupEntity addGroup(GroupEntity group) {
        GroupEntity save = repository.save(group);
        try {
            // 使用账户作为存储桶
            if (!bucketService.bucketExists(save.getId()))
                bucketService.makeBucket(save.getId());
            return save;
        } catch (Exception e) {
            e.printStackTrace();
            repository.delete(save);
            log.error("创建用户的存储桶失败！");
            return null;
        }
    }

    public GroupEntity updateGroup(GroupEntity group) throws IllegalAccessException {
        mongoOperations.upsert(new Query(Criteria.where("_id").is(group.getId())), UpdateUtil.getUpdateValues(group), group.getClass());
        Optional<GroupEntity> byId = repository.findById(group.getId());
        return byId.orElse(null);
    }

    public ResponseData<Boolean> deleteGroup(String id) {
        ResponseData<Boolean> response = new ResponseData<>();
        Optional<GroupEntity> entity = repository.findById(id);
        if (!entity.isPresent()) {
            response.setMessage("组不存在");
            response.setData(Boolean.FALSE);
            response.setCode(ResponseCode.BUSINESS_ERROR.getCode());
            return response;
        }
        try {
            Iterable<Result<Item>> results = bucketService.listObjects(entity.get().getId(), null, false, false);
            if (results != null && results.iterator().hasNext()) {
                response.setMessage("请先处理该组里的文件");
                response.setData(Boolean.FALSE);
                response.setCode(ResponseCode.BUSINESS_ERROR.getCode());
                return response;
            }
            bucketService.removeBucket(entity.get().getId());
            repository.deleteById(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        response.setMessage("成功");
        response.setData(Boolean.TRUE);
        response.setCode(ResponseCode.SUCCESS.getCode());
        return response;
    }

    public GroupEntity findById(String id) {
        Optional<GroupEntity> byId = repository.findById(id);
        return byId.orElse(null);
    }

    public Page<GroupEntity> getGroupPage(int current, int size, Sort sort) {
        final Page<GroupEntity> all = repository.findAll(PageRequest.of(current, size, sort));
        return all;
    }

    public List<GroupEntity> getAll() {
        return repository.findAll();
    }

    public List<GroupEntity> getByIds(List<String> ids) {
        Iterable<GroupEntity> allById = repository.findAllById(ids);
        ArrayList<GroupEntity> groups = new ArrayList<>();
        for (GroupEntity groupEntity : allById) {
            groups.add(groupEntity);
        }
        return groups;
    }
}
